#!/bin/bash
##  This program is free software: you can redistribute it and/or modify
##  it under the terms of the GNU General Public License as published by
##  the Free Software Foundation, either version 3 of the License, or
##  (at your option) any later version.
##  
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  GNU General Public License for more details.
##  
##  You should have received a copy of the GNU General Public License
##  along with this program.  If not, see <http://www.gnu.org/licenses/>.

##  This script is hosted here: https://code.google.com/p/brake/
##  The basis for this to work is the excelent HandBrakeCLI tool.

# Defaults
DEVICE="/dev/sr0"
OUTPUTDIR="$HOME/Videos/Rips/$( date +%s )"
MINDURATION="1800"
LANGUAGES="Deutsch,English"
TITLES="" #Searching for titles, otherwise specify -t "2 3 4" for title two, three and four.
WAIT=0
EJECT=0
SUBTITLES=0

# Error codes and messages
ERR_ARGS=10
ERR_NO_DVD=11
ERR_TOOLCHAIN=12
USAGE="Usage: $( basename $0 ) [-d /dev/device-or-file] -o [output/basedir] [-m Min. duration in minutes] [-l Deutsch,English] [-s(ubtitles)] [-t <scan for titles> ] [-w(ait)] [-e(ject)] "
VERSION="brake V. 0.0.3; GPLv3; 2012-12-08"

function parseArgs() {
	while getopts hvd:o:m:l:st:we OPT; do
		case "$OPT" in
		h)
			echo $USAGE
			exit 0;
			;;
		v)
			echo $VERSION
			exit 0;
			;;
		d)
			DEVICE="$OPTARG"
			;;
		o)
			OUTPUTDIR="$OPTARG"
			;;
		m)
			let MINDURATION=$OPTARG*60
			;;
		l)
			LANGUAGES="$OPTARG"
			;;
		s)	
			SUBTITLES=1
			;;
		t)	
			TITLES="$OPTARG"
			;;
		w)
			WAIT=1
			;;
		e)
			EJECT=1
			;;
		\?)
			echo $USAGE >&2 
			exit $ERR_ARGS
			;;

		esac
	done
}

function getLangCodes() {
	local RESULT=
	for LANG in $( echo "$LANGUAGES" | tr "," " "); do 
		echo -n " Language \"$LANG\": "
		LANGCODE=$( HandBrakeCLI --input $DEVICE --scan --title $TITLE 2>&1 | 
				grep "[0-9]\+, $LANG.*Hz" |
				cut -d"+" -f 2 |
				cut -d"," -f 1 |
				cut -d" " -f2 | 
				head -n1
			)
		if [ -z $LANGCODE ]; then
			echo " MISSING!"
		else
			echo " #$LANGCODE"
		fi

		RESULT=$RESULT,$LANGCODE
	done
	LANGCODES=$RESULT
}

function getSubtitleCodes() {
	local RESULT=
	for LANG in $( echo "$LANGUAGES" | tr "," " "); do 
		echo -n " Subtitle \"$LANG\": "
		LANGCODE=$( HandBrakeCLI --input $DEVICE --scan --title $TITLE 2>&1 | 
				grep "[0-9]\+, $LANG.*VOBSUB" |
				cut -d"+" -f 2 |
				cut -d"," -f 1 |
				cut -d" " -f2 | 
				head -n1
			)
		if [ -z $LANGCODE ]; then
			echo " MISSING!"
		else
			echo " #$LANGCODE"
		fi

		RESULT=$RESULT,$LANGCODE
	done
	SUBTITLECODES=$RESULT
}

function getDvdSerial() {
	HandBrakeCLI --input $DEVICE --scan 2>&1 | grep 'DVD Serial Number:' | cut -d":" -f 3 | cut -d" " -f2
}

function checkToolAvailable() {
	hash $1 2>/dev/null || {
		echo "Tool '$1' not found." >&2
		exit $ERR_TOOLCHAIN
	}
}

function main() {
	checkToolAvailable "HandBrakeCLI"

	DVDSERIAL=$(getDvdSerial)
	if [ "$WAIT" -eq 1 ]; then
		echo -n "($( date +%T )): Waiting for DVD at $DEVICE"
		while [ -z $DVDSERIAL ] ; do
			echo -n "."
			sleep 1
			DVDSERIAL=$(getDvdSerial)
		done
		echo ": ready"
	else
		if [ -z $DVDSERIAL ] ; then
			echo "No DVD found/recognized at $DEVICE" >&2
	  		exit $ERR_NO_DVD
		fi
	fi

	echo "Output directory will be $OUTPUTDIR-$DVDSERIAL"

	DVDTITLE=$(HandBrakeCLI --input $DEVICE --scan 2>&1 | grep 'DVD Title:' | cut -d":" -f 3 | cut -d" " -f2)

	if [ -z "$TITLES" ]; then	
		echo "($( date +%T )): Scanning $DEVICE for titles > $MINDURATION secs"
		TITLES=$(HandBrakeCLI --input $DEVICE --scan --title 0 --min-duration $MINDURATION 0 2>&1 | grep '+ title [0-9][0-9]\?:' | cut -d " " -f 3 | cut -d ":" -f 1 | tr "\n" " ")
	fi

	echo "($( date +%T )): Found: "
	echo " DVD: $DVDTITLE ($DVDSERIAL)"
	echo " Titles: $TITLES"
	
	mkdir -p "$OUTPUTDIR-$DVDSERIAL"
	for TITLE in $TITLES; do
		echo "($( date +%T )): Now processing title #$TITLE"

		FILE="$OUTPUTDIR-$DVDSERIAL/$DVDTITLE-$TITLE"
		echo " Log to: $FILE.log"

		echo "($( date +%T )): Scanning title #$TITLE for audio tracks."
		getLangCodes		

		if [ "$SUBTITLES" -eq 1 ]; then
			echo "($( date +%T )): Scanning title #$TITLE for subtitles."
			getSubtitleCodes
		fi

		while true; do echo -ne "\r ($( date +%T )): $(tail -n1 $FILE.log | grep Encoding | col -b; sleep 1s)" ; done & 2> /dev/null
		PID=$! 

		if [ "$SUBTITLES" -eq 1 ]; then
			HandBrakeCLI --input $DEVICE --title $TITLE --preset "Normal" --markers --format mp4 -a $LANGCODES -s $SUBTITLECODES --output "$FILE.mp4" &> "$FILE.log"
		else 
			HandBrakeCLI --input $DEVICE --title $TITLE --preset "Normal" --markers --format mp4 -a $LANGCODES --output "$FILE.mp4" &> "$FILE.log"
		fi

		kill $PID &> /dev/null
		echo
	done

	if [ "$EJECT" -eq 1 ]; then
		eject $DEVICE
	fi
	echo "($( date +%T )): Done."
}

parseArgs $@
main $@
